package cloud.maque.sso.client.service.impl;

import cloud.maque.common.core.consts.MediaTypes;
import cloud.maque.common.core.enums.LoginType;
import cloud.maque.conf.MaqueProperties;
import cloud.maque.sso.client.model.ThridSite;
import cloud.maque.sso.client.service.SsoUserService;
import cloud.maque.sso.client.service.Oauth2Service;
import cloud.maque.sso.client.utils.SoMap;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.alibaba.fastjson2.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Service
public class Oauth2ServiceImpl implements Oauth2Service {


    @Autowired
    MaqueProperties maqueProperties;

    @Autowired
    SsoUserService ssoUserService;

    /**
     * 模式三：密码式-授权登录
     *
     * @param username
     * @param password
     * @return
     */
    @Override
    public SaResult PasswordLogin(String username, String password) {

        OkHttpClient client = new OkHttpClient();
        Map<String, Object> bodyMap = new HashMap<>();

        RequestBody body = RequestBody.create(JSON.toJSONString(bodyMap), MediaTypes.JSON.getMediaType());

        HttpUrl.Builder urlBuilder = Objects.requireNonNull(HttpUrl.parse(maqueProperties.getOauth2().getClient().getServerUrl() + "/oauth2/token")).newBuilder();
        urlBuilder.addQueryParameter("grant_type", "password");
        urlBuilder.addQueryParameter("username", username);
        urlBuilder.addQueryParameter("password", password);
        urlBuilder.addQueryParameter("scope", "openid,userinfo");
        urlBuilder.addQueryParameter("client_id", maqueProperties.getOauth2().getClient().getClientId());
        urlBuilder.addQueryParameter("client_secret", maqueProperties.getOauth2().getClient().getClientSecret());
        String url = urlBuilder.build().toString();

        Request request = new Request.Builder().url(url).post(body).build();

        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                // 处理响应体
                return ssoUserService.process(response.body().string());

            } else {
                return SaResult.error(response.message());
            }
        } catch (IOException e) {
            return SaResult.error(e.getMessage());
        }
    }

    /**
     * 登录并绑定第三方网站
     *
     * @param username
     * @param password
     * @param thrid
     * @return
     */
    @Override
    public SaResult LongAndBind(String username, String password, ThridSite thrid) {

        Assert.notNull(thrid.getThridType(), "第三方类型不能为空");
        Assert.notNull(thrid.getUserId(), "第三方用户ID不能为空");
        Assert.notNull(thrid.getUserName(), "第三方用户名不能为空");


        OkHttpClient client = new OkHttpClient();
        Map<String, Object> bodyMap = new HashMap<>();

        RequestBody body = RequestBody.create(JSON.toJSONString(bodyMap), MediaTypes.JSON.getMediaType());

        HttpUrl.Builder urlBuilder = Objects.requireNonNull(HttpUrl.parse(maqueProperties.getOauth2().getClient().getServerUrl() + "/oauth2/token")).newBuilder();
        urlBuilder.addQueryParameter("grant_type", "password");
        urlBuilder.addQueryParameter("username", username);
        urlBuilder.addQueryParameter("password", password);
        urlBuilder.addQueryParameter("scope", "openid,userinfo");
        urlBuilder.addQueryParameter("client_id", maqueProperties.getOauth2().getClient().getClientId());
        urlBuilder.addQueryParameter("client_secret", maqueProperties.getOauth2().getClient().getClientSecret());
        String url = urlBuilder.build().toString();

        Request request = new Request.Builder().url(url).post(body).build();

        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                // 处理响应体
                return ssoUserService.loginAndBind(response.body().string(), username, thrid);

            } else {
                return SaResult.error(response.message());
            }
        } catch (IOException e) {
            return SaResult.error(e.getMessage());
        }
    }

    /**
     * 第三方的认证登录后来获取本站的Token,比如微信等
     *
     * @param userId
     * @return
     */
    @Override
    public SaResult ThrirdGetAccessToken(LoginType loginType, String userId) {
        // 第三方ThridOauth2

        OkHttpClient client = new OkHttpClient();
        Map<String, Object> bodyMap = new HashMap<>();

        RequestBody body = RequestBody.create(JSON.toJSONString(bodyMap), MediaTypes.JSON.getMediaType());

        HttpUrl.Builder urlBuilder = Objects.requireNonNull(HttpUrl.parse(maqueProperties.getOauth2().getClient().getServerUrl() + "/oauth2/token")).newBuilder();
        urlBuilder.addQueryParameter("grant_type", "third_oauth2");
        urlBuilder.addQueryParameter("thirdUserId", userId);
        urlBuilder.addQueryParameter("thirdType", loginType.name());
        urlBuilder.addQueryParameter("scope", "openid,userinfo");
        urlBuilder.addQueryParameter("client_id", maqueProperties.getOauth2().getClient().getClientId());
        urlBuilder.addQueryParameter("client_secret", maqueProperties.getOauth2().getClient().getClientSecret());
        String url = urlBuilder.build().toString();

        Request request = new Request.Builder().url(url).post(body).build();

        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                // 处理响应体
                return ssoUserService.process(response.body().string());

            } else {
                return SaResult.error(response.message());
            }
        } catch (IOException e) {
            return SaResult.error(e.getMessage());
        }
    }

    @Override
    public SaResult SendPhoneCode(String phone) {
        // 第三方ThridOauth2

        OkHttpClient client = new OkHttpClient();
        Map<String, Object> bodyMap = new HashMap<>();
        bodyMap.put("phone", phone);

        RequestBody body = RequestBody.create(JSON.toJSONString(bodyMap), MediaTypes.JSON.getMediaType());

        HttpUrl.Builder urlBuilder = Objects.requireNonNull(HttpUrl.parse(maqueProperties.getOauth2().getClient().getServerUrl() + "/oauth2/sendPhoneCode")).newBuilder();
        urlBuilder.addQueryParameter("client_id", maqueProperties.getOauth2().getClient().getClientId());
        urlBuilder.addQueryParameter("client_secret", maqueProperties.getOauth2().getClient().getClientSecret());
        String url = urlBuilder.build().toString();

        Request request = new Request.Builder().url(url).post(body).build();

        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                SaResult rasult = JSON.parseObject(response.body().string(), SaResult.class);
                return rasult;

            } else {
                return SaResult.error(response.message());
            }
        } catch (IOException e) {
            return SaResult.error(e.getMessage());
        }
    }

    @Override
    public SaResult PhoneCodeLogin(String phone, String code) {
        OkHttpClient client = new OkHttpClient();
        Map<String, Object> bodyMap = new HashMap<>();

        RequestBody body = RequestBody.create(JSON.toJSONString(bodyMap), MediaTypes.JSON.getMediaType());

        HttpUrl.Builder urlBuilder = Objects.requireNonNull(HttpUrl.parse(maqueProperties.getOauth2().getClient().getServerUrl() + "/oauth2/token")).newBuilder();
        urlBuilder.addQueryParameter("grant_type", "phone_code");
        urlBuilder.addQueryParameter("phone", phone);
        urlBuilder.addQueryParameter("code", code);
        urlBuilder.addQueryParameter("scope", "openid,userinfo");
        urlBuilder.addQueryParameter("client_id", maqueProperties.getOauth2().getClient().getClientId());
        urlBuilder.addQueryParameter("client_secret", maqueProperties.getOauth2().getClient().getClientSecret());
        String url = urlBuilder.build().toString();

        Request request = new Request.Builder().url(url).post(body).build();

        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                // 处理响应体
                return ssoUserService.process(response.body().string());

            } else {
                return SaResult.error(response.message());
            }
        } catch (IOException e) {
            return SaResult.error(e.getMessage());
        }
    }

    @Override
    public SaResult TotpLogin(String username, String password, String bind, String code) {
        OkHttpClient client = new OkHttpClient();
        Map<String, Object> bodyMap = new HashMap<>();

        RequestBody body = RequestBody.create(JSON.toJSONString(bodyMap), MediaTypes.JSON.getMediaType());

        HttpUrl.Builder urlBuilder = Objects.requireNonNull(HttpUrl.parse(maqueProperties.getOauth2().getClient().getServerUrl() + "/oauth2/token")).newBuilder();
        urlBuilder.addQueryParameter("grant_type", "totp");
        urlBuilder.addQueryParameter("username", username);
        urlBuilder.addQueryParameter("password", password);
        urlBuilder.addQueryParameter("bind", bind);
        urlBuilder.addQueryParameter("code", code);
        urlBuilder.addQueryParameter("scope", "openid,userinfo");
        urlBuilder.addQueryParameter("client_id", maqueProperties.getOauth2().getClient().getClientId());
        urlBuilder.addQueryParameter("client_secret", maqueProperties.getOauth2().getClient().getClientSecret());
        String url = urlBuilder.build().toString();

        Request request = new Request.Builder().url(url).post(body).build();

        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                // 处理响应体
                String bodyStr = response.body().string();
                SaResult rasult = JSON.parseObject(bodyStr, SaResult.class);
                if (!rasult.getCode().equals(200)) {
                    return rasult;
                } else {
                    return ssoUserService.process(bodyStr);
                }

            } else {
                return SaResult.error(response.message());
            }
        } catch (IOException e) {
            return SaResult.error(e.getMessage());
        }
    }
}
